package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.List;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.bean.BeanUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInElderDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.util.CodeGenerator;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.impl.cookie.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.Arrays;

/**
 * 入住Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-10-07
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;

    /**
     * 查询入住
     * 
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckIn selectCheckInById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 申请入住
     *
     * @param dto
     * @return
     */
    @Override
    public void apply(CheckInApplyDto dto) {
        //dto中的属性为 老人信息、家属信息、入住配置、签约办理 每个属性都为一个对象,家属信息为一个集合
        //该业务的目的是为了将各对应的数据插入到对应的数据库表中

        //1.根据数据库中的老人表中的身份证(id_card_no)判断老人是否入住
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
         //1.1将数据库老人表中(已入住即启用状态)的数据查询出来与dto中的老人信息身份证进行比较
        queryWrapper.eq(Elder::getIdCardNo,dto.getCheckInElderDto().getIdCardNo());
        queryWrapper.eq(Elder::getStatus,1);
         //1.2查询已入住的老人
        Elder elder = elderMapper.selectOne(queryWrapper);//指定查询条件
        //1.3判断是否已入住
        if(elder != null ){
            //已入住
           throw new BaseException("该老人已入住");
        }
        //2.此时更新床位状态为已入住
          //2.1根据选择的床位id查询到对应的床位信息
        Bed bed = bedMapper.selectById(dto.getCheckInConfigDto().getBedId());
          //2.2将该床位的状态改为已入住1
        bed.setBedStatus(1);
          //2.3更新该床位信息
        bedMapper.updateById(bed);

        //3.更新或保存老人数据
        elder = insertOrUpdate(bed, dto.getCheckInElderDto());

        //生成合同编号
        String contractNo = "HT" + CodeGenerator.generateContractNumber();
        //4.新增签约办理 (将前端传递的合同信息插入到合同表中)
        intsertContract(contractNo,elder, dto);

        //5.新增入住信息
        CheckIn checkIn = insertCheckInInfo(elder, dto);

        //6.新增入住配置
         insertCheckInConfig(checkIn.getId(), dto);


    }


    /**
     * 新增入住配置
     * @param id
     * @param  dto 前端传递的入住配置信息
     *
     *
     * */
    private void insertCheckInConfig(Long id, CheckInApplyDto dto) {
        CheckInConfig checkInConfig = new CheckInConfig();
        BeanUtils.copyProperties(dto.getCheckInConfigDto(),checkInConfig);
        checkInConfig.setCheckInId(id);
        checkInConfigMapper.insert(checkInConfig);
    }

    /**
    *
    * 新增入住信息
    * @param elder 老人信息
    * @param dto 前端传递的入住信息
    *  @return CheckIn
    *
    * */
    private CheckIn insertCheckInInfo(Elder elder, CheckInApplyDto dto) {
        CheckIn checkIn = new CheckIn();
        //根据数据库表补全入住信息
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        checkIn.setIdCardNo(elder.getIdCardNo());
        checkIn.setNursingLevelName(dto.getCheckInConfigDto().getNursingLevelName());
        checkIn.setBedNumber(elder.getBedNumber());
        checkIn.setStartDate(dto.getCheckInConfigDto().getStartDate());
        checkIn.setEndDate(dto.getCheckInConfigDto().getEndDate());
        checkIn.setRemark(JSON.toJSONString(dto.getElderFamilyDtoList()));
        checkIn.setStatus(0);
        checkInMapper.insert(checkIn);
        return checkIn;
    }

    /**
     * 新增签约办理
     *
     * @param contractNo
     * @param elder
     * @param dto        前端传递的签约办理信息
     */
    private void intsertContract(String contractNo, Elder elder, CheckInApplyDto dto) {
        //此处创建对象的目的是为了将前端参数传递进来,并补充数据
        Contract contract = new Contract();
        //属性拷贝
        BeanUtils.copyProperties(dto.getCheckInContractDto(),contract);
        //给合同中填写老人基本数据 合同编号
        contract.setElderId(Integer.valueOf(String.valueOf(elder.getId()))); //
        contract.setContractNumber(contractNo); //合同编号
        contract.setElderName(elder.getName()); //合同中的老人姓名

        //状态 开始时间 结束时间
         contract.setStartDate(dto.getCheckInConfigDto().getStartDate());
         contract.setEndDate(dto.getCheckInConfigDto().getEndDate());
         //签约时间小于等于当前时间 合同生效
         if(contract.getSignDate().isBefore(LocalDateTime.now())){
             contract.setStatus(1);
         }else{
             contract.setStatus(0);
         }
         contractMapper.insert(contract);


    }

    /**
       *  新增或更新老人信息
       *  @param bed
       *  @param  checkInElderDto 前端传递的老人信息
       *
       * */
    private Elder insertOrUpdate(Bed bed, CheckInElderDto checkInElderDto){
        //准备老人属性
        Elder elder = new Elder();
        //将dto中的属性拷贝到elder中
        BeanUtils.copyProperties(checkInElderDto,elder);
        //根据Elder实体类可以判断bed缺少的数据  因此参数中要传递bed 参数
        elder.setBedId(bed.getId()); //床位id
        elder.setBedNumber(bed.getBedNumber()); //床位编号
        elder.setStatus(1); //将老人的状态改为已入住
        //查询老人信息(身份证号 状态不为1)
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>(); //????????
        queryWrapper.eq(Elder::getIdCardNo,elder.getIdCardNo()).ne(Elder::getStatus,1);//?????????
        Elder  elderDb = elderMapper.selectOne(queryWrapper);//???????
        if(ObjectUtils.isNotEmpty(elderDb)){
            //更新
            elderMapper.updateById(elder);
        }else{
            //新增
            elderMapper.insert(elder);
        }
        return elder;
    }

    /**
     * 根据id查询入住详情
     * 返回值为CheckInDetailVo(包括老人信息、入住配置信息、入住合同信息、入住信息 )
     *
     * @param id
     */
    @Override
    public CheckInDetailVo detail(Long id) {

        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
      //1.根据id查询入住信息
        CheckIn checkIn = checkInMapper.selectCheckInById(id);
        //2.根据入住信息中的老人id查询老人信息
        CheckInElderVo checkInElderVo = elderMapper.selectCheckInElderVoById(checkIn.getElderId());
         //根据当前系统时间与老人生日计算年龄
        String birthday = checkInElderVo.getBirthday();
        //将字符串转换为LocalDate类型
        LocalDate birthdayDate = LocalDate.parse(birthday);
        //获取当前时间
        LocalDate now = LocalDate.now();
        //当前时间减去生日时间
        Period period = Period.between(birthdayDate, now);
        //获取年龄
        checkInElderVo.setAge(period.getYears());

        //3.查询合同
        Contract contract = contractMapper.selectContractByElderId(checkIn.getElderId());

        //4.根据入住信息中的id查询入住配置信息
        CheckInConfigVo checkInConfigVo = checkInConfigMapper.selectCheckInConfigVoById(id);
        //5.转换家属信息为List<ElderFamilyVo>
        List<ElderFamilyVo> elderFamilyVoList = JSON.parseArray(checkIn.getRemark(), ElderFamilyVo.class);
        //6.将以上信息封装到CheckInDetailVo中
        checkInDetailVo.setCheckInElderVo(checkInElderVo);
        checkInDetailVo.setElderFamilyVoList(elderFamilyVoList);
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
        checkInDetailVo.setContract(contract);

        return checkInDetailVo;
    }
}
